package com.ylc.chat.server;

import com.ylc.chat.common.Request;
import com.ylc.chat.common.Response;
import com.ylc.chat.common.ResponseStatus;
import com.ylc.chat.entity.Chatrecord;
import com.ylc.chat.entity.User;
import com.ylc.chat.service.ChatrecordService;
import com.ylc.chat.service.FriendsService;
import com.ylc.chat.service.UserService;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * @Author: ylc
 * @Description:请求功能具体实现
 */
public class RequestProcessor implements Runnable{
    //当前正在请求服务器的客户端Socket
    private Socket currentClientSocket;

    UserService userService = new UserService();
    FriendsService friendsService = new FriendsService();
    ChatrecordService chatrecordService = new ChatrecordService();

    public RequestProcessor(Socket currentClientSocket){
        this.currentClientSocket = currentClientSocket;
    }

    @Override
    public void run() {
        boolean flag = true; //是否不间断监听
        try{
            OnlineClientIOCache currentClientIOCache = new OnlineClientIOCache(
                    new ObjectInputStream(currentClientSocket.getInputStream()),
                    new ObjectOutputStream(currentClientSocket.getOutputStream()));
            while(flag){ //不停地读取客户端发过来的请求对象
                //从请求输入流中读取到客户端提交的请求对象
                Request request = (Request)currentClientIOCache.getOis().readObject();
                System.out.println("Server读取了客户端的请求:" + request.getAction());
                //获取请求中的动作
                String action = request.getAction();
                if("userRegister".equals(action)){      //用户注册
                    register(currentClientIOCache, request);
                }else if("userLogin".equals(action)){  //用户登录
                    login(currentClientIOCache, request);
                }else if("exit".equals(action)){
                   flag = logout(currentClientIOCache, request);
                }else if("getFriends".equals(action)){
                    getFriends(currentClientIOCache, request);
                }else if("getRecord".equals(action)){
                    getRecord(currentClientIOCache, request);
                }else if("sendRecord".equals(action)){
                    sendRecord(currentClientIOCache, request);
                }

            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 发送消息
     * @param currentClientIO
     * @param request
     */
    private void sendRecord(OnlineClientIOCache currentClientIO, Request request) throws IOException{
        Chatrecord chatrecord = (Chatrecord)request.getAttribute("chatrecord");

        int res = chatrecordService.addRecord(chatrecord);

        Response response = new Response();
        if(res == 1){
            response.setStatus(ResponseStatus.OK);
        }

        //向客户端响应数据
        currentClientIO.getOos().writeObject(response);
        currentClientIO.getOos().flush();
    }

    /**
     * 获取聊天记录
     * @param currentClientIO
     * @param request
     */
    private void getRecord(OnlineClientIOCache currentClientIO, Request request) throws IOException {
//        int sendUid = (int)request.getAttribute("sendUid");
        int sendUid = getFromUser(currentClientIO).getUid();
        int receiveUid = (int)request.getAttribute("receiveUid");

        // 获取向好友发送的消息
        List<Chatrecord> sendRecord = chatrecordService.getRecordByUid(sendUid, receiveUid);
        // 获取好友向我发送的消息
        List<Chatrecord> receiveRecord = chatrecordService.getRecordByUid(receiveUid, sendUid);

        //创建一个响应对象
        Response response = new Response();
        response.setStatus(ResponseStatus.OK);
        response.setData("sendRecord", sendRecord);
        response.setData("receiveRecord", receiveRecord);
        //向客户端响应数据
        currentClientIO.getOos().writeObject(response);
        currentClientIO.getOos().flush();
    }

    /**
     * 获取好友列表
     * @param currentClientIO
     * @param request
     * @throws IOException
     */
    private void getFriends(OnlineClientIOCache currentClientIO, Request request) throws IOException {
        int uid = (int)request.getAttribute("uid");
        String[] friends = friendsService.getFriends(Integer.valueOf(uid));
        List<User> userList = new ArrayList<>();
        for (int i = 0; i < friends.length; i++) {
            User user = userService.getUser(Integer.valueOf(friends[i]));
            userList.add(user);
        }
        //创建一个响应对象
        Response response = new Response();
        response.setStatus(ResponseStatus.OK);
        response.setData("friends", userList);
        //向客户端响应数据
        currentClientIO.getOos().writeObject(response);
        currentClientIO.getOos().flush();
    }

    /**
     * 登录
     * @param currentClientIO
     * @param request
     * @throws IOException
     */
    private void login(OnlineClientIOCache currentClientIO, Request request) throws IOException {
        String uname = (String)request.getAttribute("uname");
        String password = (String) request.getAttribute("password");

        User user = userService.login(uname, password);

        //创建一个响应对象
        Response response = new Response();
        if(null != user){
            if(ServerDataBuffer.onlineUsersMap.containsKey(user.getUname())){ //用户已经登录了
                response.setStatus(ResponseStatus.OK);
                response.setData("msg", "该用户已在其他客户端中上线了！");

            }else { //正确登录
                ServerDataBuffer.onlineUsersMap.put(user.getUname(), user); //添加到在线用户

                // 修改用户状态为上线
                userService.updateOnline(user.getUname(),1);

                //设置在线用户
                response.setData("onlineUsers",
                        new CopyOnWriteArrayList<User>(ServerDataBuffer.onlineUsersMap.values()));
                response.setStatus(ResponseStatus.OK);
                response.setData("user", user);

                //把当前上线的用户IO添加到缓存Map中
                ServerDataBuffer.onlineUserIOCacheMap.put(user.getUname(),currentClientIO);
            }
        }else{ //登录失败
            response.setStatus(ResponseStatus.OK);
            response.setData("msg", "账号或密码不正确！");
        }
        //向客户端响应数据
        currentClientIO.getOos().writeObject(response);
        currentClientIO.getOos().flush();
    }

    /**
     * 注册
     * @param currentClientIO
     * @param request
     * @throws IOException
     */
    private void register(OnlineClientIOCache currentClientIO, Request request) throws IOException {
        String uname = (String)request.getAttribute("uname");
        String password = (String) request.getAttribute("password");

        UserService userService = new UserService();
        int res = userService.addUser(uname,password);

        Response response = new Response();  //创建一个响应对象
        if(res > 0){    // 注册成功
            User user = userService.getUser(uname);
            response.setStatus(ResponseStatus.OK);
            response.setData("user", user);
            //添加到在线用户
            ServerDataBuffer.onlineUsersMap.put(user.getUname(), user);

            // 修改用户状态为上线
            userService.updateOnline(user.getUname(),1);

//            //通知其它用户有人上线了
//            Response response2 = new Response();
//            response2.setType(ResponseType.LOGIN);
//            response2.setData("loginUser", user);
//            iteratorResponse(response2);

            //设置在线用户
            response.setData("onlineUsers",
                    new CopyOnWriteArrayList<User>(ServerDataBuffer.onlineUsersMap.values()));
            response.setStatus(ResponseStatus.OK);
            response.setData("user", user);

            //把当前上线的用户IO添加到缓存Map中
            ServerDataBuffer.onlineUserIOCacheMap.put(user.getUname(),currentClientIO);

            response.setStatus(ResponseStatus.OK);
            response.setData("msg", "注册成功！");
        }else{
            response.setStatus(ResponseStatus.SERVER_ERROR);
            response.setData("msg", "注册失败！");
        }
        currentClientIO.getOos().writeObject(response);
        currentClientIO.getOos().flush();
    }

    /**
     * 退出
     * @param currentClientIO
     * @param request
     * @return
     * @throws IOException
     */
    public boolean logout(OnlineClientIOCache currentClientIO, Request request) throws IOException{
        System.out.println(currentClientSocket.getInetAddress().getHostAddress()
                + ":" + currentClientSocket.getPort() + "离线");

        User user = (User)request.getAttribute("user");
        // 把当前上线客户端的IO从Map中删除
        ServerDataBuffer.onlineUserIOCacheMap.remove(user.getUname());
        // 从在线用户缓存Map中删除当前用户
        ServerDataBuffer.onlineUsersMap.remove(user.getUname());
        // 修改用户状态为下线
        userService.updateOnline(user.getUname(),0);

        Response response = new Response();
//        //通知其它用户有人离线了
//        response.setType(ResponseType.LOGOUT);
        response.setData("logoutUser", user);
        currentClientIO.getOos().writeObject(response);
        currentClientIO.getOos().flush();
        currentClientSocket.close();
        //通知所有其它在线客户端
        iteratorResponse(response);
        //断开监听
        return false;
    }

    /**
     * 通知所有在线客户端该用户已下线
     * @param response
     * @throws IOException
     */
    private void iteratorResponse(Response response) throws IOException {
        for(OnlineClientIOCache onlineUserIO : ServerDataBuffer.onlineUserIOCacheMap.values()){
            ObjectOutputStream oos = onlineUserIO.getOos();
            oos.writeObject(response);
            oos.flush();
        }
    }

    /**
     * 通过IO流判断请求来自于那个用户
     * @param currentClientIO
     * @return
     */
    private User getFromUser(OnlineClientIOCache currentClientIO){
        User fromUser = null;
        for(String u : ServerDataBuffer.onlineUserIOCacheMap.keySet()){
            if(currentClientIO == ServerDataBuffer.onlineUserIOCacheMap.get(u)){
                fromUser = ServerDataBuffer.onlineUsersMap.get(u);
            }
        }
        return fromUser;
    }
}
